package educar.models;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.LinkedList;

import educar.db.DbConnection;
import educar.db.JPA;

/**
 * 
 * @author Baldani-Ocejo-Padula
 * 
 * Clase que modela una materia de la universidad
 *
 */
public class Materia
{
    //TODO check: si dniResponsable != null entonces es el dni de un Docente

    private static JPA jpa = new JPA();
    private static final String noAsignado = "-1";
    private String nombre;
    private String codigo;
    private String dniResponsable;

   
    /**
     * @return una respresentacion en cadena de texto con datos de la materia
     */
    public String toString()
    {
    	return nombre  + " - " +  codigo;
    }
    
    /**
     * Constructor de clase
     * 
     * @param codigo codigo que va a tener la materia
     * @param nombre nombre de la materia
     * @param dniResponsable dni del docente que esta a cargo de la materia
     */
    private Materia(String codigo, String nombre, String dniResponsable)
    {
        this.codigo = codigo;
        this.nombre = nombre;
        this.dniResponsable = dniResponsable;
    }

    /**
     * Constructor de clase
     * 
     * @param nombre nombre de la materia
     */
    public Materia(String nombre)
    {
        this.nombre = nombre;
        codigo = noAsignado;
        dniResponsable = null;
    }

    /**
     * Constructor de clase
     * 
     * @param nombre nombre de la materia
     * @param dniResponsable dni del docente responsable de la materia
     */
    public Materia(String nombre, String dniResponsable)
    {
        this.nombre = nombre;
        this.dniResponsable = dniResponsable;//TODO: verificar!
        codigo = noAsignado;
    }

    /**
     * Metodo para crear una persistencia en la base de datos de este objeto Materia
     * 
     * @return verdadero si se pudo guardar, falso en caso contrario
     */
    public boolean save()
    {
        String[] columns = { "codigoMateria", "nombreMateria", "dniDoc" };
        PreparedStatement stm = jpa.newRecord(DbConnection.bd+".materia", columns);
        try
        {
            stm.setString(1, null);
            stm.setString(2, nombre);
            stm.setString(3, dniResponsable);
        }
        catch (SQLException e)
        {
            e.printStackTrace();
            return false;
        }

        jpa.create(stm);
        actualizarCodigoAlMaximo();

        return true;
    }

    //para utilizar al guardar un cargo en la base de datos
    //y obtener el codigo que le fue asignado en el objeto
    //utilizar sólo inmediatamente despues de guardar en la base de datos
    private void actualizarCodigoAlMaximo()
    {
        ResultSet rs = jpa.showMaxColumn("materia", "codigoMateria");
        try
        {
            if (rs.next())
            {
                this.codigo = rs.getString(1);
            }
        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }
    }

    /**
     * Metodo para actualizar en la base de datos la informacion de esta materia
     * con el estado actual de esta instancia
     * 
     * @throws materiaNotFound si la materia no se encuentra en sistema
     */
    public void update() throws materiaNotFound
    {
        if (codigo.compareTo(noAsignado) != 0)
        {
            HashMap<String, String> m = new HashMap<String, String>();
            m.put("nombreMateria", nombre);
            m.put("dniDoc", dniResponsable);
            jpa.genericUpdate("materia", m, "codigoMateria", codigo);
        }
        else
            throw new materiaNotFound();
    }

    /**
     * Metodo para destruir en la base de datos esta materia
     * 
     * @throws materiaNotFound si la materia que se quiere destruir no existe
     */
    public void destroy() throws materiaNotFound
    {
        if (codigo.compareTo(noAsignado) != 0)
            jpa.destroy("materia", "codigoMateria", codigo);
        else
            throw new materiaNotFound();
    }

    /**
     * @param nombre nombre de la materia que se desea obtener
     * @return un objeto de tipo materia con el nombre pasado por parametro
     * buscando la informacion necesaria en la base de datos
     * @throws materiaNotFound si no existe una materia con ese nombre en base de datos
     */
    public static Materia getMateriabyName(String nombre) throws materiaNotFound
    {
        ResultSet rs = null;
        Materia m = null;

        rs = jpa.getByField("materia", "nombreMateria", nombre);

        try
        {
            if (rs.next())
            {
                m = new Materia(rs.getString(1), rs.getString(2), rs.getString(3));
            }
            else
            {
                throw new materiaNotFound();
            }
        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }

        return m;
    }

    /**
     * @param codigo codigo de la materia que se desea obtener
     * @return un objeto de tipo materia con el codigo pasado por parametro
     * buscando la informacion necesaria en la base de datos
     * @throws materiaNotFound si no existe una materia con ese codigo en base de datos
     */
    public static Materia getMateriabyCodigo(String codigo) throws materiaNotFound
    {
        ResultSet rs = null;
        Materia m = null;

        rs = jpa.getByField("materia", "codigoMateria", codigo);

        try
        {
            if (rs.next())
            {
                m = new Materia(codigo, rs.getString(2), rs.getString(3));
            }
            else
            {
                throw new materiaNotFound();
            }
        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }

        return m;
    }
    
    /**
     * 
     * @return devuelve una lista con todas las materias
     */
    public static LinkedList<Materia> getAll()
    {
        ResultSet rs = null;
        LinkedList<Materia> materias = new LinkedList<Materia>();
        rs = jpa.showAllOrderBy("materia", "codigoMateria");
        try
        {
            while (rs.next())
            {
                materias.add(new Materia(rs.getString(1), rs.getString(2), rs.getString(3)));
            }

        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }

        return materias;
    }

    /**
     * 
     * @param d docente del cual se quieren buscar las materias
     * @return una lista de materias que tienen como responsable al docente pasado por parametro
     */
    public static LinkedList<Materia> getAllByResponsable(Docente d)
    {
        LinkedList<Materia> l = new LinkedList<Materia>();
        ResultSet rs = jpa.getByField("materia", "dniDoc", d.getDni());
        try
        {
            while (rs.next())
            {
                l.add(new Materia(rs.getString(1), rs.getString(2), rs.getString(3)));
            }
        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }

        return l;
    }

    /**
     * 
     * @return una lista con todas las actividades de esta materia
     */
    public LinkedList<Actividad> getAllActividades()
    {
        return Actividad.getAllByMateria(this);
    }

    /**
     * 
     * @return un arreglo con una representacion en cadena de texto de todas las materias
     */
    public static String[] getAllMateriasArray()
    {
        LinkedList<Materia> l = getAll(); //TODO: pedir unicamente la columa nombre a la db
        String[] materias = new String[l.size()];
        for (int i = 0; i < l.size(); i++)
            materias[i] = l.get(i).toString();

        return materias;
    }


    /**
     * 
     * @param auxiliar metodo para agregar un auxiliar docente a la materia
     * @return verdadero si se pudo agregar, falso en caso contrario
     */
    public boolean agregarAuxiliar(String auxiliar)
    {
        String[] columns = { "codigoMate", "dniDocent" };
        PreparedStatement stm = jpa.newRecord(DbConnection.bd+".asigna", columns);
        try
        {
            stm.setString(1, codigo);
            stm.setString(2, auxiliar);
        }
        catch (SQLException e)
        {
            e.printStackTrace();
            return false;
        }

        return jpa.create(stm);
    }


    /**
     * 
     * @param dni dni del docente para el cual se quiere saber si es responsable o no
     * @return verdadero si es responsable, falso en otro caso
     * @throws materiaNotFound si la materia no existe en la base de datos
     */
    public Boolean isResponsable(String dni) throws materiaNotFound
    {
        ResultSet rs = null;

        rs = jpa.getByField("materia", "codigoMateria", codigo);
        Boolean rta = false;
        try
        {
            while (rs.next())
            {
                if (rs.getString(2).compareTo(dni) == 0)
                    rta = true;
            }
        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }

        return rta;
    }

    public Boolean isAuxiliar(String dni)
    {
        ResultSet rs = null;

        rs = jpa.getByField("asigna", "codigoMateria", codigo);
        Boolean rta = false;
        try
        {
            while (rs.next())
            {
                if (rs.getString(2).compareTo(dni) == 0)
                    rta = true;
            }
        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }

        return rta;
    }


    public String getNombre()
    {
        return nombre;
    }

    public String getCodigo()
    {
        return codigo;
    }

    public String getDniResponsable()
    {
        return dniResponsable;
    }

    public void setNombre(String nombre)
    {
        this.nombre = nombre;
    }

    public void setDniResponsable(String dni)
    {
        this.dniResponsable = dni;
    }

    public void quitarResponsable()
    {
        dniResponsable = null;
    }

    public void setCodigo(String codigo)
    {
        this.codigo = codigo;
    }

    public String[] getAllAuxiliares()
    {
        ResultSet rs = jpa.getByField("asigna", "codigoMate", codigo);
        LinkedList<String> lista = new LinkedList<String>();
        try
        {
            while (rs.next())
                lista.add(rs.getString(2));
        }
        catch (SQLException s1)
        {
        }
        String[] auxiliares = new String[lista.size()];
        for (int i = 0; i < lista.size(); i++)

            auxiliares[i] = lista.get(i);

        return auxiliares;
    }

    public String[] getAllNombresAuxiliares()
    {
        String[] dnis = getAllAuxiliares();
        String[] nombres = new String[dnis.length];
        for (int i = 0; i < dnis.length; i++)
        {
            try
            {
                nombres[i] = (Docente.getDocenteByDni(dnis[i])).toString();
            }
            catch (docenteNotFound e)
            {
                e.printStackTrace();
            }
        }
        return nombres;
    }

    public String getNombreResponsable()
    {
        String nombre = "No asignado";
        try
        {
            nombre = Docente.getDocenteByDni(dniResponsable).toString();
        }
        catch (docenteNotFound e)
        {

        }
        return nombre;
    }
    /*TODO:
        public static void eliminarResponsable(String dni)
        {}
    */

    /*TODO:
    public static void eliminarAuxiliar(String dni)
    {
        jpa.destroy(DbConnection.bd+"", "asigna", dni);
    }
    */
}
